package org.chaiyi.template.core.framework.mongo;

import com.mongodb.ConnectionString;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import org.chaiyi.template.core.common.supporter.MongoSupporter;
import org.chaiyi.template.core.common.supporter.entity.MongoSetting;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.query.BasicUpdate;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.concurrent.ConcurrentHashMap;

@Component
public class MongoManager {


    private final MongoCustomConversions mongoCustomConversions;

    private final ConcurrentHashMap<String, ReactiveMongoOperations> mongoMap;

    public MongoManager(MongoCustomConversions mongoCustomConversions) {
        this.mongoCustomConversions = mongoCustomConversions;
        mongoMap = new ConcurrentHashMap<>();
    }


    public Mono<ReactiveMongoOperations> getOperations(Mono<MongoSupporter> supporter) {
        return supporter.map(MongoSupporter::getMongoSetting)
                .map(MongoSetting::getUri)
                .flatMap(this::getOperations);
    }

    private Mono<ReactiveMongoOperations> getOperations(String uri) {
        return Mono.defer(() -> Mono.just(mongoMap.computeIfAbsent(uri, this::build)));
    }

    public ReactiveMongoOperations build(String uri) {
        ConnectionString connectionString = new ConnectionString(uri);
        MongoClient mongoClient = MongoClients.create(connectionString);
        ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoClient, connectionString.getDatabase());
        MappingMongoConverter converter = (MappingMongoConverter) template.getConverter();
        converter.setCustomConversions(mongoCustomConversions);
        converter.afterPropertiesSet();
        return template;
    }


}
